package model
{
	import controller.GameController;
	
	import flash.display.Loader;
	import flash.events.*;
	import flash.media.Sound;
	import flash.net.FileReference;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.utils.Dictionary;
	import flash.xml.XMLNode;
	
	public class xmlHandler
	{
		private var xml:XML;
		private var xmlloader:URLLoader;
		private var paramDict:Dictionary = new Dictionary();
		private var count:int;
		private var explanationFiles:Array = new Array();
		private var gameControl:GameController;
		
		public function xmlHandler(gameControl:GameController)
		{
			this.gameControl = gameControl;
			var url:URLRequest = new URLRequest("./gameData/gameData.xml");
			xmlloader = new URLLoader();
			xmlloader.addEventListener(Event.COMPLETE, parseXML);
			xmlloader.load(url);	
		}
		
		/**
		 * Liest die XML ein und speichert sie in der Klassenvariablen
		 */
		private function parseXML(evt:Event):void{
			
			xml = XML(xmlloader.data);
			xml.ignoreWhite = true;  
			
			trace("XML erfolgreich eingelesen!");
			//trace(xml);
			this.gameControl.playIntroduction();
		//	this.gameControl.initGameStartAfterIntro();
			
			//Auskommentieren, wenn valide XML vorhanden!
			
			//checkXML(0);
			
			//Auskommentieren wenn Fragen genügend getestet wurden
			//getQuestionToLevel(1);
			
		}
		
		/**
		 * Wählt aus den Fragen eines Levels zufällig eine Frage aus und gibt diese als
		 * Question-Objekt (bereits mit Sounddatei und Produkten) zurück.
		 */
		public function getQuestionToLevel(level:uint):Question
		{
			var questionsToLevel:Array = new Array();
			for each(var questionTag:XML in xml.questions.question){
				if(questionTag.level == level.toString()){
					questionsToLevel.push(questionTag);
				}
			}
			trace("Anzahl Fragen zu dem Level: "+questionsToLevel.length);
			var rand:int = Math.floor(Math.random()*questionsToLevel.length);
			var choosenQuestion:XML = questionsToLevel[rand];
			
			//ID abfragen
			var question:Question = new Question(level);
			question.setQuestionID(choosenQuestion.ID);
			trace("Gewählte Frage: "+choosenQuestion.ID);
			
			var questionSound:Sound = new Sound();
			questionSound.load(new URLRequest(choosenQuestion.questionSound));
			question.setQuestionSound(questionSound);
			trace("Sounddatei zur Frage: "+choosenQuestion.questionSound);
			
			var rightProducts:Array = this.getRightProducts(choosenQuestion);
		//	trace(rightProducts.length);
			question.setRightProducts(rightProducts);
			
			var wrongProducts:Array = this.getWrongProducts(choosenQuestion);
		//	trace(wrongProducts.length);
			question.setWrongProducts(wrongProducts);
			
			return question;
		}
		
		/**
		 * Wählt aus den richtigen Produkten zu einer Frage zufällig 5 Produkte aus und gibt diese als
		 * Product-Objekte in einem Array zurück 
		 */
		private function getRightProducts(question:XML):Array
		{ 
			var rightObjects:Array = new Array();
			for each(var rightObject:XML in question.rightObjects.object){
				rightObjects.push(rightObject);
			}
			//trace("Anzahl richtiger Produkte: "+rightObjects.length);
			
			var rightObjects5:Array = new Array();
			for(var i:int=0; i<5; i++){
				var rand2:int = Math.floor(Math.random()*rightObjects.length);
				//trace("Anzahl richtiger Objekte in Schleife: "+rightObjects.length);
				//trace("Zufallszahl: "+rand2);
				rightObjects5.push(rightObjects[rand2]);
				rightObjects.splice(rand2,1);//rand2 = Startindex, 1=deleteCount
			}
			//trace("Gewählte 5 richtige Objekte: "+rightObjects5);
			
			var rightProducts:Array = new Array();
			for each(var rightProduct:XML in rightObjects5){
				var id:String = rightProduct.ID;
				//trace("Produkt-ID: "+id);
				var explanationSoundPath:String = rightProduct.sound;
				//trace("Explanation-Sound: "+explanationSoundPath);
				var picPath:String;
				var nameSoundPath:String;
				
				for each(var product:XML in xml.products.product){
					if(product.ID == id){
						picPath = product.picture;
						//trace("Picture: "+picPath);
						nameSoundPath = product.nameSound;
						//trace("Name-Sound: "+nameSoundPath);
					}
				}
				
				var productComplete:Product = new Product(id, picPath, nameSoundPath, explanationSoundPath);
				rightProducts.push(productComplete);
			}
			//trace("Länge des endgültigen Arrays:"+rightProducts.length);
			return rightProducts;
		}
		
		/**
		 * Wählt aus den falschen Produkten zu einer Frage zufällig 10 Produkte aus und gibt diese als
		 * Product-Objekte in einem Array zurück 
		 */
		private function getWrongProducts(question:XML):Array
		{
			var wrongObjects:Array = new Array();
			for each(var wrongObject:XML in question.wrongObjects.object){
				wrongObjects.push(wrongObject);
			}
			//trace("Anzahl falscher Produkte: "+wrongObjects.length);
			
			var wrongObjects10:Array = new Array();
			for(var j:int=0; j<10; j++){
				var rand3:int = Math.floor(Math.random()*wrongObjects.length);
				//trace("Anzahl falscher Objekte in Schleife: "+wrongObjects.length);
				//trace("Zufallszahl: "+rand3);
				wrongObjects10.push(wrongObjects[rand3]);
				wrongObjects.splice(rand3,1);//rand2 = Startindex, 1=deleteCount
			}
			//trace("Gewählte 10 falsche Objekte: "+wrongObjects10);
			var wrongProducts:Array = new Array();
			for each(var wrongProduct:XML in wrongObjects10){
				var id:String = wrongProduct.ID;
				//trace("Produkt-ID: "+id);
				var explanationSoundPath:String = wrongProduct.sound;
				//trace("Explanation-Sound: "+explanationSoundPath);
				var picPath:String;
				var nameSoundPath:String;
				
				for each(var product:XML in xml.products.product){
					if(product.ID.toString() == id){
						picPath = product.picture;
						//trace("Picture: "+picPath);
						nameSoundPath = product.nameSound;
						//trace("Name-Sound: "+nameSoundPath);
					}
				}
				
				var object:Product = new Product(id, picPath, nameSoundPath, explanationSoundPath);
				wrongProducts.push(object);
			}
			//trace("Länge des endgültigen Arrays:"+wrongProducts.length);
			return wrongProducts;
		}
		
		/**
		 * Prüft die XML auf Fehler (in Dateinamen und/oder Produkt-IDs)
		 */
		private function checkXML(count:int):void{
			switch(count){
				case 0:
					checkIDs();
					break;
				case 1:
					this.count=0;
					checkProductImages();
					break;
				case 2:
					trace("Prüfung der Produktbilder abgeschlossen.");
					this.count=0;
					checkProductNames();
					break;
				case 3:
					trace("Prüfung der Produktnamens-Sounddateien abgeschlossen.");
					this.count=0;
					checkProductExplanations();
					break;
				case 4:
					trace("Prüfung der Erklärungs-Sounddateien abgeschlossen.");
					this.count=0;
					checkQuestionSounds();
					break;
				case 5:
					trace("Alle Überprüfungen abgeschlossen!");
					break;
			}
		}
		
		/**
		 * Prüft ob die Dateinamen der Fragestellungen korrekt geschrieben sind
		 */
		private function checkQuestionSounds():void{
			var numberOfQuestions:int = xml.questions.children().length();
			//trace("Anzahl Produkte: "+numberOfQuestions+", count: "+this.count);	
			var question:XML = xml.questions.question[this.count];
			
			var url:String = question.questionSound;
			this.count++;
			if (url.indexOf("./gameData/audio/questions") >= 0){
				//trace("Frage URL: "+url);
				
				var request:URLRequest = new URLRequest(url);					
				var loader:URLLoader = new URLLoader;
				
				loader.load(request);
				
				paramDict[loader] = url;
				
				loader.addEventListener(IOErrorEvent.IO_ERROR, falseFile);
				loader.addEventListener(Event.COMPLETE, completed);
				
				//trace("Loader gestartet");
			}else{
				//trace("Count in Fkt: "+this.count);
				if (this.count < numberOfQuestions){
					checkQuestionSounds();
				} else{
					checkXML(5);	
				}				
			}	
			
			function falseFile(e:IOErrorEvent):void{
				var params:Object = paramDict[e.currentTarget];
				URLLoader(e.target).removeEventListener(IOErrorEvent.IO_ERROR, falseFile);
				URLLoader(e.target).removeEventListener(Event.COMPLETE, completed);
				trace("Nicht gefundene Fragen-Sounddatei: "+params.toString());
				if (count < numberOfQuestions){
					checkQuestionSounds();
				} else{
					checkXML(5);	
				}
			}	
			
			function completed(e:Event):void{
				//trace("Count in complete: "+count);
				URLLoader(e.target).removeEventListener(IOErrorEvent.IO_ERROR, falseFile);
				URLLoader(e.target).removeEventListener(Event.COMPLETE, completed);
				if (count < numberOfQuestions){
					checkQuestionSounds();
				} else{
					checkXML(5);	
				}
			}
		}
		
		/**
		 * Prüft ob alle Dateinamen der Fragenbezogenen Produktbeschreibungen
		 * korrekt geschrieben sind.
		 */
		private function checkProductExplanations():void{
			if(count == 0){
				var numberOfQuestions:int = xml.questions.children().length();
				//trace("Anzahl der Fragen: "+numberOfQuestions);
				for (var i:int = 0; i<numberOfQuestions ; i++){
					for each(var objectRight:XML in xml.questions.question[i].rightObjects.object){
						explanationFiles.push(objectRight.sound);
					}
					for each(var objectWrong:XML in xml.questions.question[i].wrongObjects.object){
						explanationFiles.push(objectWrong.sound);
					}
				}
			}
			
			var numberOfFiles:int = explanationFiles.length;
			//trace("Anzahl Dateien: "+numberOfFiles+", count: "+this.count);	
			
			var url:String = explanationFiles.shift();
			this.count++;
			if (url.indexOf("./gameData/audio/explanations") >= 0){
				//trace("Erklärungs-URL: "+url);
				
				var request:URLRequest = new URLRequest(url);					
				var loader:URLLoader = new URLLoader;
				
				loader.load(request);
				
				paramDict[loader] = url;
				
				loader.addEventListener(IOErrorEvent.IO_ERROR, falseFile);
				loader.addEventListener(Event.COMPLETE, completed);
				
				//trace("Loader gestartet");
			}else{
				//trace("Count in Fkt: "+this.count);
				if (this.explanationFiles.length > 0){
					checkProductExplanations();
				} else{
					checkXML(4);	
				}				
			}	
			
			function falseFile(e:IOErrorEvent):void{
				var params:Object = paramDict[e.currentTarget];
				URLLoader(e.target).removeEventListener(IOErrorEvent.IO_ERROR, falseFile);
				URLLoader(e.target).removeEventListener(Event.COMPLETE, completed);
				trace("Nicht gefundene Erklärungs-Sounddatei: "+params.toString());
				if (explanationFiles.length > 0){
					checkProductExplanations();
				} else{
					checkXML(4);	
				}
			}	
			
			function completed(e:Event):void{
				//trace("Count in complete: "+count);
				URLLoader(e.target).removeEventListener(IOErrorEvent.IO_ERROR, falseFile);
				//trace("Nach removeEventListener(IOErrorEvent.IO_ERROR, falseFile)");
				URLLoader(e.target).removeEventListener(Event.COMPLETE, completed);
				//trace("Nach removeEventListener(Event.COMPLETE, completed)");
				if (explanationFiles.length > 0){
					checkProductExplanations();
				} else{
					checkXML(4);	
				}
			}
		}
		
		/**
		 * Prüft ob alle Dateinamen der Produkt-Namen-Sounddateien korrekt geschrieben wurden.
		 */
		private function checkProductNames():void{
			var numberOfProducts:int = xml.products.children().length();
			//trace("Anzahl Produkte: "+numberOfProducts+", count: "+this.count);	
			var product:XML = xml.products.product[this.count];
			
			var url:String = product.nameSound;
			this.count++;
			if (url.indexOf("./gameData/audio/products") >= 0){
				//trace("Bild URL: "+url);
				
				var request:URLRequest = new URLRequest(url);					
				var loader:URLLoader = new URLLoader;
				
				loader.load(request);
				
				paramDict[loader] = url;
				
				loader.addEventListener(IOErrorEvent.IO_ERROR, falseFile);
				loader.addEventListener(Event.COMPLETE, completed);
				
				//trace("Loader gestartet");
			}else{
				//trace("Count in Fkt: "+this.count);
				if (this.count < numberOfProducts){
					checkProductNames();
				} else{
					checkXML(3);	
				}				
			}	
			
			function falseFile(e:IOErrorEvent):void{
				var params:Object = paramDict[e.currentTarget];
				URLLoader(e.target).removeEventListener(IOErrorEvent.IO_ERROR, falseFile);
				URLLoader(e.target).removeEventListener(Event.COMPLETE, completed);
				trace("Nicht gefundene Produktnamen-Sounddatei: "+params.toString());
				if (count < numberOfProducts){
					checkProductNames();
				} else{
					checkXML(3);	
				}
			}	
			
			function completed(e:Event):void{
				//trace("Count in complete: "+count);
				URLLoader(e.target).removeEventListener(IOErrorEvent.IO_ERROR, falseFile);
				URLLoader(e.target).removeEventListener(Event.COMPLETE, completed);
				if (count < numberOfProducts){
					checkProductNames();
				} else{
					checkXML(3);	
				}
			}
		}
		
		/**
		 * Prüft ob alle Dateinamen der Produktbilder korrekt geschrieben wurden.
		 */
		private function checkProductImages():void{
			var numberOfProducts:int = xml.products.children().length();
			//trace("Anzahl Produkte: "+numberOfProducts+", count: "+count);	
			var product:XML = xml.products.product[this.count];
			
			var url:String = product.picture;
			this.count++;
			if (url.indexOf("./gameData/images") >= 0){
				//trace("Bild URL: "+url);
				
				var request:URLRequest = new URLRequest(url);					
				var loader:URLLoader = new URLLoader;
				
				loader.load(request);
				
				paramDict[loader] = url;
				
				loader.addEventListener(IOErrorEvent.IO_ERROR, falseFile);
				loader.addEventListener(Event.COMPLETE, completed);
				
				//trace("Loader gestartet");
			}else{
				if (this.count < numberOfProducts){
					checkProductImages();
				} else{
					checkXML(2);	
				}				
			}	
			
			function falseFile(e:IOErrorEvent):void{
				var params:Object = paramDict[e.currentTarget];
				URLLoader(e.target).removeEventListener(IOErrorEvent.IO_ERROR, falseFile);
				URLLoader(e.target).removeEventListener(Event.COMPLETE, completed);
				trace("Nicht gefundene Produktbild-Datei: "+params.toString());
				if (this.count < numberOfProducts){
					checkProductImages();
				} else{
					checkXML(2);	
				}
			}	
			
			function completed(e:Event):void{
				URLLoader(e.target).removeEventListener(IOErrorEvent.IO_ERROR, falseFile);
				URLLoader(e.target).removeEventListener(Event.COMPLETE, completed);
				if (this.count < numberOfProducts){
					checkProductImages();
				} else{
					checkXML(2);	
				}
			}
		}
		
		/**
		 * Prüft ob alle Produkt-IDs korrekt geschrieben wurden
		 */
		private function checkIDs():void{
			var wrongID:Boolean = false;
			var numberOfProducts:int = xml.products.children().length();
			var productIDs:Array = new Array();
			
			for (var i:int = 0; i < numberOfProducts; i++){
				var ID:String = xml.products.product[i].ID;
				productIDs.push(ID);
			}
			
			for each (var question:XML in xml.questions.question){
				for each (var productID in question.rightObjects.object.ID){
					if(productIDs.indexOf(productID.toString())<0){
						trace("Fehlerhafte Produkt-ID gefunden: ");
						trace("Frage: "+question.ID+"; level: "+question.level+"; ID: "+productID);
						wrongID = true;
					}
				}
			}
			
			if(wrongID == false){
				trace("Alle Produkt-IDs in der XML sind korrekt!");
			}
			
			checkXML(1);
		}
	}
}